package com.uuah.server.config.spring.parsers.assembly;

import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;

import com.uuah.server.config.spring.UuahHierarchicalBeanDefinitionParserDelegate;
import com.uuah.server.config.spring.parsers.assembly.configuration.IPropertyConfiguration;

/**
 * This is used by
 * {@link com.uuah.server.config.spring.parsers.delegate.MapDefinitionParserMutator} -
 * it takes a normal bean definition and re-packages it as a map (rather than
 * individual values). The difference between this and
 * {@link com.uuah.server.config.spring.parsers.assembly.AttributeMapBeanAssemblerFactory}
 * is that this allows child elements to generate the properties (it's an ugly
 * consequence of the fact that BDPs are called before nested children - this is
 * a hack that gets "re-called" after the children to complete the work).
 */
public class TwoStageMapBeanAssembler extends AbstractMapBeanAssembler {

	private TwoStageMapBeanAssemblerFactory.BeanAssemblerStore store;

	public TwoStageMapBeanAssembler(
			TwoStageMapBeanAssemblerFactory.BeanAssemblerStore store,
			IPropertyConfiguration beanConfig, BeanDefinitionBuilder bean,
			IPropertyConfiguration targetConfig, BeanDefinition target) {
		super(beanConfig, bean, targetConfig, target);
		this.store = store;
	}

	/**
	 * We overwrite this method to populate a map instead of inserting the
	 * definition. However, the bean definition is not complete until all child
	 * elements have been parsed - and that parsing happens after this routine
	 * is called. So on first pass we set a flag in the definition. This is
	 * picked up by the main driver loop (
	 * {@link com.UuahHierarchicalBeanDefinitionParserDelegate.uuah.server.config.spring.UuahHierarchicalBeanDefinitionParserDelegate}
	 * ) and our enclosing bean definition parser is called again. At the same
	 * time, to avoid complicating otherwise "normal" BDPs, we pass this
	 * assembler to a callback, so that it can be called the second time in a
	 * more direct way.
	 */
	public void insertBeanInTarget(String oldName) {
		assertTargetPresent();

		if (UuahHierarchicalBeanDefinitionParserDelegate.testFlag(getBean()
				.getBeanDefinition(),
				UuahHierarchicalBeanDefinitionParserDelegate.UUAH_POST_CHILDREN)) {
			insertDefinitionAsMap(oldName);
		} else {
			// called for the first time, so set the flag and store this
			// assembler for
			// later processing
			UuahHierarchicalBeanDefinitionParserDelegate
					.setFlag(
							getBean().getBeanDefinition(),
							UuahHierarchicalBeanDefinitionParserDelegate.UUAH_POST_CHILDREN);
			store.saveBeanAssembler(this);
		}
	}

}
